Syles VCL Delphi - John COLIBRI. |
- résumé : présentation des Styles Vcl : séléction de styles pré-définis, utilisation de Vcl Style Designer, fichiers de style .VSF, chargement de styles à l'éxécution, écriture de tStyleHooks, points à surveiller pour nos
propres composants, styles et thèmes Delphi 7
- mots clé : Delphi Vcl Styles, tStyleManager, SetStyle, tStyleHook, StyleServices, GetElementDetails, RegisterStyleHook, UnregisterStyleHook, UpdateColor
- logiciel utilisé : Windows XP personnel, Delphi Xe2
- matériel utilisé : Pentium 2.800 Mhz, 512 Meg de mémoire, 250 Giga disque dur
- champ d'application : Delphi Xe2 et suivants sous Windows
- niveau : développeur Delphi
- plan :
1 - Syles Vcl Delphi Xe2
Les styles permettent de modifier les couleurs et l'apparence des contrôles de toutes les fenêtres d'une application. Ces systèmes d'apparences, appelés "thèmes", "skins", "styles" permettent par
exemple de doter notre fenêtre d'un cadre doré Louis XVI, ou de dessiner nos contrôles avec une apparence noire "graphite". Il existait déjà, dérivé semble-t-il de tVirtualTreeview de Mike LISCHKE
plusieurs systèmes de changement d'apparence, ayant culminé avec les thèmes, y compris l'unité UXTHEME.PAS (2003).
2 - Principe Les grandes lignes tout d'abord :
- la couleur, les traits, les images de la forme et des contrôles visuels sont par défaut définis par Windows. Windows permet aussi de définir des familles de styles "Panneau de configuration | Apparences thèmes" et "Panneau de
configuration | Apparences | Apparences"
- nous pouvons demander à Delphi de dessiner en utilisons un style que nous pouvons définir. C'est l'objet de cet article.
Dans ce cas:
- les propriétés telles que mon_controle.Color seront ignorées et remplacées par les propriétés que vous avez sélectionnées
- la mécanique des styles de la VCL place des Hooks qui se chargent
d'effectuer le dessin. En gros les méthodes de dessin sont détournées vers la mécanique de Styles Delphi.
Comme les Hooks sont niché au plus bas niveau Delphi possible, les contrôles standard de la Vcl, la plupart des contrôles des produits
tiers, nos propres composants graphiques, utiliseront le style choisi.
- Cette mécanique n'est pas parfaite :
- il peu y avoir du scintillement ou quelques irrégularités (stries verticales, par exemple) lors de l'affichage
- si nous chargeons (ou laissons l'utilisateur choisir) les styles à l'exécution, le résultat peut être un peu inattendu. Les styles sélectionnés à la conception ont le mérite de pouvoir être soigneusement vérifiés
- certaines zones sont connues pour ne pas bénéficier des styles (OwnerDraw, surbrillance etc)
3 - Définition de Styles par les Options 3.1 - Sélection et Prévisualisation
Voici comment utiliser les options d'un projet pour modifier les styles:
3.2 - Sélection d'un style Pour que le style soit utilisé par notre application
4 - Changement de style à l'exécution 4.1 - Chargement de la liste des styles
Nous pouvons aussi laisser l'utilisateur sélectionner un style. Pour cela nous utilisons le tStyleManager, en appelant SetStyle
Class Procedure SetStyle(Const Name: String); overload;
|
Le nom fourni doit naturellement être un des noms connus de Delphi. Pour cela, le mieux est de charger tous les noms dans une tListBox, laisser
l'utilisateur sélectionner un nom, puis appeler SetStyle.
Les styles sont définis dans des fichiers .VSF (Vcl Style File), situé (sur notre PC) dans :
C:\Documents and Settings\All Users\Documents\RAD Studio\9.0\Styles | Voici le contenu de nos fichiers .VSF:
Ce chemin est défini par la variable d'environnement BDSCOMMONDIR "Tools | Options | Environnment Options | Environment Variables"
4.2 - Projet de changement dynamique de style Voici comment charger les noms des fichiers .VSF :
| lancez Delphi (Xe2 ou supérieur) | |
créez une application "File | New | Vcl Forms Application - Delphi", sauvegardez la sous p_09_vcl_styles | |
créez une Procedure qui charge les noms des fichiers de style Vcl:
Uses System.IOUtils; // tDirectory
Const k_BDSUSERDIR= 'C:\Documents and Settings\All Users\Documents\RAD Studio\9.0\';
Procedure list_BDSUSERDIR_vsf_files(p_c_strings: tStrings);
// -- fill ListBoxDiskStyles with the names of styles from our style folder
Var l_styles_dir, l_file_name: String;
Begin p_c_strings.Clear;
l_styles_dir:= k_BDSUSERDIR+ 'Styles\';
For l_file_name In TDirectory.GetFiles(l_styles_dir,
'*'+ TStyleEngine.FileExtension) Do
p_c_strings.Add(ExtractFileName(l_file_name));
End; // list_BDSUSERDIR_vsf_files | Modifiez éventuellement la constante définissant le chemin des .VSF |
| posez une tListBox, nommez-la vsf_style_listbox_ | |
posez un tButton qui charge les styles dans ListBox1:
Procedure TForm1.list_BDSUSERDIR_vsf_styles_Click(Sender: TObject); //
Begin list_BDSUSERDIR_vsf_files(vsf_style_listbox_.Items);
End; // list_registered_styles | | |
compilez et exécutez | | voici le résultat:
C'est donc actuellement "Windows" le seul style utilisable |
Les styles disponibles (chargés et accessible par notre projet) peuvent être affichés par
| tapez la procédure qui liste les styles
Procedure list_registered_styles(p_c_strings: tStrings);
// -- fill ListBoxLoadedStyles with the names of styles
Var l_style_name: String; Begin
p_c_strings.Clear;
For l_style_name In TStyleManager.StyleNames Do
If p_c_strings.IndexOf(l_style_name)= - 1
Then p_c_strings.Add(l_style_name);
End; // list_registered_styles | | |
posez une tListBox, nommez-la registered_styles_listbox_, posez un tButton qui la remplit:
Procedure TForm1.list_registered_styles_Click(Sender: TObject);
Begin list_registered_styles(registered_styles_listbox_.Items);
End; // list_registered_styles_Click | | |
compilez et exécutez | | voici le résultat:
|
Voici comment charger un style à l'exécution : | écrivez la procédure qui utilise le tStyleManager pour charger un style en
mémoire:
Uses Vcl.Styles, Vcl.Themes;
Procedure load_BDSUSERDIR_vsf_style(Const pk_vsf_style_filename: String);
Begin If FileExists(pk_vsf_style_filename)
Then TStyleManager.LoadFromFile(pk_vsf_style_filename);
End; // load_BDSUSERDIR_vsf_style | | |
créez l'événement vsf_style_listbox_.OnClick et chargez le style correspondant, puis réaffiche les styles enregistrés:
Procedure TForm1.vsf_style_listbox_Click(Sender: TObject);
Var l_vsf_filename: String; Begin
With vsf_style_listbox_ Do Begin
l_vsf_filename:= Items[ItemIndex];
load_BDSUSERDIR_vsf_style(k_BDSUSERDIR+ 'styles\'+ l_vsf_filename);
// -- remove from vsf name list
Items.Delete(ItemIndex); End;
// -- redisplay the registered styles list_registered_styles_Click(Nil);
End; // vsf_style_listbox_Click | | |
compilez et exécutez, cliquez "Golden Graphite" | | voici le résultat: |
A présent nous pouvons sélectionner l'un des styles chargés en mémoire: |
créez registered_styles_listbox_.OnClick qui charge le style sélectionné:
Procedure TForm1.registered_styles_listbox_Click(Sender: TObject);
Var l_style_name: String; Begin
With registered_styles_listbox_ Do
l_style_name:= Items[ItemIndex];
TStyleManager.SetStyle(l_style_name);
End; // registered_styles_listbox_Click | | |
posez quelques contrôles "représentatifs" sur Form1 (un tEdit, un tPageControl, tTreeView, un tPopupMenu etc) | |
compilez et exécutez, cliquez "Golden Graphite" | | voici le résultat: | | ouvrez le popup | |
ni la ligne sélectionnée dans registered_styles_listbox_ ni PopupMenu1 ne sont "stylés" (sélection en bleu, menu en gris):
|
5 - Vcl Style Designer 5.1 - VclStyleDesigner.exe Cet outil permet de créer de nouveaux styles, en général en partant d'un style existant. Cet .EXE
- se trouve dans C:\Program Files\Embarcadero\RAD Studio\9.0\bin
- peut être invoqué depuis "Tools | Vcl Style Designer"
- est redistribuable: nous pouvons le fournir à des graphistes externes pour
qu'ils définissent de nouveaux styles que nous pouvons ensuite utiliser pour nos applications
Notez que certaines parties de la doc wiki mentionne cet utilitaire sous le nom de "Bitmap" Style Designer"
5.2 - Modification d'une image globale Le Style Designer peut présenter dans un seul .PNG les éléments graphiques utilisés par un style. Pour modifier globalement les couleurs d'un style, il suffit ainsi
- de charger une ce ces images, de modifier les couleurs du .PNG (avec PaintBrush, Gimp, PaintShopPro ou autre)
- de sauvegarder cette image, puis la recharger dans le Style Designer
- de prévisualiser, éventuellement le rendu
- de sauvegarder le résultat dans un nouveau fichier .VSF que nous pouvons ensuite utiliser comme n'importe quel style pré-défini par Delphi
Voici un exemple de modification globale de Golden Graphite
| lancez le Style Designer par "Tools | Vcl Style Designer" | | voici le résultat
| |
chargez un style existant, par exemple "Golden Graphite", en cliquant "File | Open" et cherchez un style dans C:\Documents and Settings\All Users\Documents\RAD Studio\9.0\Styles |
| dans le TreeView de gauche, cliquez "Images | Style.png" | | voci les éléments de style:
| |
sauvegardez l'image .PNG pour pouvoir la modifier. Nous avons utilisé un répertoire \my_png_styles et un nom "my_style.png" Donc cliquez l'icône "export" (ou par "Image | Export", fournissez le répertoire et sélectionnez "Export" |
| voici le répertoire |
| cliquez "export" | | voici l'image rechargée dans PaintBrush:
|
Nous pouvons alors modifier les couleurs de ce .png avec n'importe quel utilitaire graphique.
Importons l'image dans le Style Designer:
5.3 - Changement d'autres éléments de style Nous avons simplement modifié globalement toutes les couleurs de l'image globale. Nous pouvons aussi modifier chaque élément individuellement en utilisant les
autres éléments du TreeView du Style Designer Pour faire court
Nous pouvons vérifier le résultat en sélectionnant "Style | Test" (ou l'icône
verte) :
Pour tout dire, à part changer - l'image d'un objet ("Objects | RadioButton | Checked | Bitmap" puis clic
droit et clic gauche pour définir l'image à utiliser)
- la couleur "Colors | EditDisabled"
- la couleur système
nous ne sommes pas arrivés à modifier les autres éléments (dans "Objects | RadioButton etc).
Vous aurez certainement plus de patience pour lire la doc http://docwiki.embarcadero.com/RADStudio/XE3/en/Creating_a_Style_using_the_Bitmap_Style_Designer
6 - Vcl tStyleHook
Pour modifier les éléments de style de façon plus fine, nous pouvons écrire une Classe dérivée de tStyleHook en modifiant les éléments dessinés. Il existe déjà toute une hiérarchie de tStyleHook présente dans Vcl.StdCtrls:
- tEditStyleHook
- tMemoStyleHook
6.1 - tEditStyleHook Le mieux pour comprendre ces tStyleHook est de désosser tEditStyleHook. Voici une partie du code :
Type TEditStyleHook=
Class(TStyleHook)
Strict Private
Procedure UpdateColors;
Strict Protected
Procedure PaintNC(Canvas: TCanvas); Override;
Procedure WndProc(Var Message: TMessage); Override;
Public
Constructor Create(AControl: TWinControl); Override;
End; // TEditStyleHook // -- TEditStyleHook
Constructor TEditStyleHook.Create(AControl: TWinControl);
Begin Inherited; OverridePaintNC:= True;
OverrideEraseBkgnd:= True; UpdateColors;
End; // Create Procedure TEditStyleHook.UpdateColors;
Const k_style_color_array: Array[Boolean] Of TStyleColor=
(scEditDisabled, scEdit);
k_style_font_array: Array[Boolean] Of TStyleFont=
(sfEditBoxTextDisabled, sfEditBoxTextNormal);
Var l_c_custom_style_services: TCustomStyleServices; Begin
l_c_custom_style_services:= StyleServices;
Brush.Color:= l_c_custom_style_services.GetStyleColor(
k_style_color_array[Control.Enabled]);
FontColor:= l_c_custom_style_services.GetStyleFontColor(
k_style_font_array[Control.Enabled]);
End; // UpdateColors
Procedure TEditStyleHook.PaintNC(Canvas: TCanvas);
Var l_c_themed_element_details: TThemedElementDetails;
l_rectangle: TRect; Begin
If StyleServices.Available Then
Begin
l_c_themed_element_details:= StyleServices.GetElementDetails(
teEditBorderNoScrollNormal);
l_rectangle:= Rect(0, 0, Control.Width, Control.Height);
InflateRect(l_rectangle, - 2, - 2);
ExcludeClipRect(Canvas.Handle, l_rectangle.Left, l_rectangle.Top,
l_rectangle.Right, l_rectangle.Bottom);
StyleServices.DrawElement(Canvas.Handle, l_c_themed_element_details,
Rect(0, 0, Control.Width, Control.Height));
End; End; // PaintNC
Procedure TEditStyleHook.WndProc(Var Message: TMessage);
Begin Case Message.Msg Of
CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC: Begin
SetTextColor(Message.WParam, ColorToRGB(FontColor));
SetBkColor(Message.WParam, ColorToRGB(Brush.Color));
Message.Result:= LRESULT(Brush.Handle);
Handled:= True;
End; CM_ENABLEDCHANGED:
Begin UpdateColors;
Handled:= False; // Allow control to handle message
End
Else Inherited WndProc(Message);
End; End; // WndProc
// -- class constructor registration
Class Constructor TCustomEdit.Create; Begin
TCustomStyleEngine.RegisterStyleHook(TCustomEdit, TEditStyleHook);
End; | et: - UpdateColors a pour vocation de lire les valeurs des couleurs et polices correspondant à certains états du contrôle.
tCustomStyleServices est une Classe qui nous permet de récupérer les valeurs provenant du style (éventuellement modifiées par le Style Designer). Pour savoir quelle couleur devra être utilisée si le tEdit est Enabled ou
non, nous utilisons If Control.Enabled
Then Brush.Color:= l_c_custom_style_services.GetStyleColor(scEditDisabled)
Else Brush.Color:= l_c_custom_style_services.GetStyleColor(scEdit);
| "UpdateColor" veut donc dire "mettez à jour la valeur tEditStyleHook.Brush.Color à partir de la table des couleurs de ce style.
Ces couleurs ainsi mises à jour pourront alors être utilisées pour dessiner le contrôle par la suite - PaintNC dessine les bordures en utilisant StyleServices.DrawElement
- la procédure WndProc analyse le type de message
- si Enabled a changé, les valeurs de Brush.Color ou FontColor sont lues dans la table de style
- si le message concerne le dessin (la couleur est la couleur par défaut ou une couleur spécifiée par l'utilisateur) les couleurs initialisées par UpdateColor sont utilisées pour effectuer le dessin
- ce tEditStyleHook est utilisée par un Class Constructor (cf Allen BAUER)
6.2 - Utilisation de tStyleHook Le principe semble donc être le suivant
- nous modifions les valeurs de polices et couleurs dans le Style Designer, pour pouvoir les charger dans UpdateColor de notre tStyleHook
- nous créons notre Classe t_xxx_style_hook dérivée de tStyleHook, et même en général d'un tStyleHook existant pour n'avoir à modifier que quelques propriétés marginales
- dans le programme qui utilise ce tStyleHook
- nous l'enregistrons notre tStyleHook
tStyleManager.Engine.RegisterStyleHook(t_yyy, t_xxx_style_hook); |
- si nous chargeons un style (comme montré précédemment) ce style utilisera nos affichages
- nous pouvons éventuellement retirer le hook par UnRegisterStyleHook
Notez qu'il existe aussi un message cm_StyleChanged. Il peut être utilisé pour récupérer les valeurs du style, puis changer les couleurs du composant pour éviter le scintillement. Important si change de forme, ou utilise des
tPageControl : si la couleur original était clWindow ou noir, si affiche avec un style coloré, aura des scintillements (le composant est d'abord peint par Windows avec les couleurs originales, puis les styles sont surajoutés)
6.3 - Premier essai Pour comprendre ce fonctionnement, nous avons simplement
Notez que - naturellement nous voyons le violet du fond, et l'orange pour l'Edit
inhibé. Mais nous ne voyons pas notre police italique, et l'affichage n'est pas parfait
6.4 - tStyleHook pour changer le fond sélectionnée
Nous avons emprunté à Rodrigo RUZ, le grand gourou des styles Vcl, un exemple qui colorie la couleur du fond d'un tEdit :
Type TWinControlClass= Class(TWinControl);
Constructor TEditStyleHookColor.Create(AControl: TWinControl);
Begin Inherited; UpdateColors;
End; // Create
Procedure TEditStyleHookColor.do_display(p_text: String);
Begin
display(Format('%-6s %s', [Control.Name, p_text]));
End; // do_display
Procedure TEditStyleHookColor.UpdateColors;
Var LStyle: TCustomStyleServices; Begin
If Control.Enabled Then
Begin
Brush.Color:= TWinControlClass(Control).Color;
FontColor:= TWinControlClass(Control).Font.Color;
End Else
Begin LStyle:= StyleServices;
Brush.Color:= LStyle.GetStyleColor(scEditDisabled);
FontColor:= LStyle.GetStyleFontColor(sfEditBoxTextDisabled);
End; End; // UpdateColors
Procedure TEditStyleHookColor.WndProc(Var Message: TMessage);
Begin Case Message.Msg Of
CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC: Begin
UpdateColors;
SetTextColor(Message.WParam, ColorToRGB(FontColor));
SetBkColor(Message.WParam, ColorToRGB(Brush.Color));
Message.Result:= LRESULT(Brush.Handle);
Handled:= True;
End; CM_ENABLEDCHANGED:
Begin UpdateColors;
Handled:= False;
End
Else Inherited WndProc(Message);
End; End; // WndProc |
Et voici le résultat après enregistrement de ce hook, avec notre style
6.5 - StyleServices
StyleServices a quelques méthodes que nous pouvons utiliser - IsSystemStyle : faux si utilise un style custom (Aqua Graphite etc)
- pour récupérer les "programmatic color" qui ont été ajustées dans le Style
Designer, nous utilisons GetStyleColor
Les valeurs possibles sont:
TStyleColor = (scBorder, scButtonDisabled, scButtonFocused, scButtonHot,
scButtonNormal, scButtonPressed, scCategoryButtons, scCategoryButtonsGradientBase,
scCategoryButtonsGradientEnd, scCategoryPanelGroup, scComboBox,
scComboBoxDisabled, scEdit, scEditDisabled, scGrid, scGenericBackground,
scGenericGradientBase, scGenericGradientEnd, scHintGradientBase,
scHintGradientEnd, scListBox, scListBoxDisabled, scListView, scPanel, scPanelDisabled,
scSplitter, scToolBarGradientBase, scToolBarGradientEnd, scTreeView, scWindow);
| Ces constantes sont utilisées pour récupérer la couleur de fond d'un élément de style, puis pour coordonner les dessins d'autres éléments d'un composant custom
Pour un tButton, nous pouvons utiliser, par exemple scButtonNormal pour le bouton relâché, et scButtonPressed pour le bouton enfoncé Notez que tous les contrôles ne sont pas dans ce énuméré. Nous n'avons rien,
par exemple, pour un tMemo. Il faudra donc utiliser les énumérés d'un tEdit - GetStyleFontColor, qui a beaucoup plus de valeurs :
tStyleFont = (
sfButtonTextDisabled, sfButtonTextFocused, sfButtonTextHot, sfButtonTextNormal, sfButtonTextPressed,
sfCaptionTextInactive, sfCaptionTextNormal,
sfCategoryPanelGroupHeaderHot, sfCategoryPanelGroupHeaderNormal, sfCatgeoryButtonsCategoryNormal,
sfCatgeoryButtonsCategorySelected,
sfCatgeoryButtonsHot, sfCatgeoryButtonsNormal, sfCatgeoryButtonsSelected,
sfCheckBoxTextDisabled, sfCheckBoxTextFocused, sfCheckBoxTextHot, sfCheckBoxTextNormal,
sfCheckBoxTextPressed,
sfComboBoxItemDisabled, sfComboBoxItemFocused, sfComboBoxItemHot, sfComboBoxItemNormal,
sfComboBoxItemSelected,
sfEditBoxTextDisabled, sfEditBoxTextFocused, sfEditBoxTextHot, sfEditBoxTextNormal,
sfEditBoxTextSelected,
sfGridItemFixedHot, sfGridItemFixedNormal, sfGridItemFixedPressed, sfGridItemNormal,
sfGridItemSelected, sfGroupBoxTextDisabled, sfGroupBoxTextNormal,
sfHeaderSectionTextDisabled, sfHeaderSectionTextHot, sfHeaderSectionTextNormal,
sfHeaderSectionTextPressed,
sfListItemTextDisabled, sfListItemTextFocused, sfListItemTextHot, sfListItemTextNormal,
sfListItemTextSelected,
sfMenuItemTextDisabled, sfMenuItemTextHot, sfMenuItemTextNormal, sfMenuItemTextSelected,
sfPanelTextDisabled, sfPanelTextNormal,
sfPopupMenuItemTextDisabled, sfPopupMenuItemTextHot, sfPopupMenuItemTextNormal,
sfPopupMenuItemTextSelected,
sfRadioButtonTextDisabled, sfRadioButtonTextFocused, sfRadioButtonTextHot, sfRadioButtonTextNormal,
sfRadioButtonTextPressed, sfSmCaptionTextInactive, sfSmCaptionTextNormal,
sfStatusPanelTextDisabled, sfStatusPanelTextNormal,
sfTabTextActiveDisabled, sfTabTextActiveHot, sfTabTextActiveNormal, sfTabTextInactiveDisabled,
sfTabTextInactiveHot, sfTabTextInactiveNormal,
sfTextLabelDisabled, sfTextLabelFocused, sfTextLabelHot, sfTextLabelNormal,
sfToolItemTextDisabled, sfToolItemTextHot, sfToolItemTextNormal, sfToolItemTextSelected,
sfTreeItemTextDisabled, sfTreeItemTextFocused, sfTreeItemTextHot, sfTreeItemTextNormal,
sfTreeItemTextSelected, sfWindowTextDisabled, sfWindowTextNormal ); |
- GetStyleSystemFont est utilisé pour récupérer une couleur qui correspond à une couleur système
Pour utiliser ces couleurs, fournit comme paramètre une couleur connue et la
fonction retourne la couleur utilisée par le style actuellement chargé
my_actual_color:= StyleServices.GetStyleSystemColor(clBtnFace |
6.6 - Parties non stylées Comme indiqué auparavant - les tMainMenu sont stylés
- less tPopupMenu le sont pas
- toutes les parties d'un contrôle ne sont pas toujours stylés, comme, par
exemple Toolbar.BorderWidth
Mentionnons aussi que toutes les formes utilisent le même style
6.7 - Les Styles et vos propres composants Quelques informations supplémentaires :
- concernant les éléments que les styles ne prennent pas toujours en compte :
- couleur tBrush par défaut
- chaque fois qu'un contrôle est créé, Delphi crée une nouvelle Handle,
avec une tBrush par défaut. Toutefois cette brosse ne sera pas synchronisée avec nos styles
- les styles actuellement ne changent pas tControl.Color. Même si nous
utilisons le style "graphite", la valeur de tEdit.Color est toujours clWhite (c'est pourquoi il faut utiliser UpdateColor pour récupérer les couleurs du style)
- contrôles "OwnerDraw"
- tout dépend d'où nos couleurs sont récupérées : si nous dessinons sur un tCanvas en utilisant clBtnFace, la couleur sera celle de Windows (et pas celle de la face des tButton de ce style)
- la couleur des textes sélectionnés (clHighLigth) ne sera pas modifié par les Styles Vcl. Il n'y a pas d'élément de style qui permet de changer cette couleur. Quel que soit le style sélectionné, aura le même style
bleu marine de Windows pour la sélection
- certains contrôles pourraient avoir des parties pour lesquelles Delphi n'a pas prévu l'élément de style. Il faudra donc coder manuellement l'affichage de ces parties
6.8 - Compatibilité arrière Pour les personnes utilisant déjà les Thèmes depuis Delphi 7 : - StyleServices seulement disponibles depuis Xe2
- pourrait utiliser des $IfDef, mais devient rapidement ingérable
- le mieux est de définir des fonctions:
- UsingSystemStyle : retourne True si <Xe2, sinon retourne False
- ActiveStyleColor : retourne la valeur
- ActiveSyleFontCOlor
- ActiveSyleSystemFontCOlor
6.9 - La Classe Vcl.Styles.tStyleManager Ce diagramme de Classe UML résume les propriétés et méthodes de tStyleManager que nous avons utilisées:
et pour les tStyleHook
7 - Remarques Quelques commentaires
- le choix de styles prédéfinis, ou même le changement global de la bitmap .PNG qui représente tous les styles sont faciles
- pour les modifications détaillées, c'est une autre histoire :
- il faut connaître les éléments de style utilisé par les contrôles usuels (scrollbars, pagecontrol etc)
- je ne suis pas arrivé à modifier les "Objects" simples, mais soit j'ai
oublié une manipulation, soit ma version (Xe2, update 1) ne le permet pas
- la modification de l'image d'un Objet est assez délicate, et peut-être est-elle prévue pour sélectionner des images autres que la .PNG globale
chargées pour modifier un composant particulier.
- les autres items de treeview (fonts, colors, syscolors) semble avoir un double rôle
- elles sont appliquées aux contrôles usuels (l'orange que nous avons mis dans les syscolor)
- elles sont destinées à être appelées depuis des tStyleHooks. Dans ce cas, il faut comprendre les correspondances entre
- à quels éléments Windows associe chaque image ou police
- quel est le nom Delphi correspondant
afin de pouvoir les lire et les appliquer à nos propres composants graphiques
En fait ces tStyleHooks semblent concerner surtout - Embarcadero
- les sociétés spécialisées dans la vente de composants (Raize, Tms etc)
- les développeurs commr RRUZ qui a passé le temps suffisant pour comprendre ces associations
- les blogs mentionnent aussi que les contrôles non-windows (tPanel) doivent être traités différemment que les contrôles standards (tButton)
- dans le Style Designer, le test (F9, la "flèche verte" ou "Style | Test"
correspond à VclStyleTest.exe situé dans \BIN. Il aurait été utile d'avoir les sources pour pouvoir y inséerer les composants que nous développons pour tester leur comportement par rapport aux composants standards inclus dans ce test
- nul doute que la doc générale et les constantes des polices et couleurs se bonifient dans le temps
8 - Télécharger le code source Delphi Vous pouvez télécharger:
Comme d'habitude: - nous vous remercions de nous signaler toute erreur, inexactitude ou
problème de téléchargement en envoyant un e-mail à jcolibri@jcolibri.com. Les corrections qui en résulteront pourront aider les prochains lecteurs
- tous vos commentaires, remarques, questions, critiques, suggestion d'article, ou mentions d'autres sources sur le même sujet seront de même les bienvenus à jcolibri@jcolibri.com.
- plus simplement, vous pouvez taper (anonymement ou en fournissant votre e-mail pour une réponse) vos commentaires ci-dessus et nous les envoyer en cliquant "envoyer" :
- et si vous avez apprécié cet article, faites connaître notre site, ajoutez un lien dans vos listes de liens ou citez-nous dans vos
blogs ou réponses sur les messageries. C'est très simple: plus nous aurons de visiteurs et de références Google, plus nous écrirons d'articles.
9 - Références
Le spécialiste incontesté des styles Vcl est Rodrigo RUZ (RRUZ dans les forums) : - des tutoriels et une librairie d'exploration avec des démos :
- de nombreux exemples concrets de résolutions de parties incomplètes des styles
- mentionnons aussi que RRUZ est très actif sur StackOverflow (pour les
styles, mais aussi dans des domaines tels que WMI)
Autre tutoriels
Et pour les constructeurs de Classe
L'article original a été écrit en Français (indentation du code pascal original)
10 - L'auteur
John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le
conseil (composants, architecture, test) et la
formation. Son site contient des articles
avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et
UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client. |